package com.gss.module.generator.core;

import cn.hutool.core.io.FileUtil;
import com.gss.module.generator.constants.CommonConstants;
import com.gss.module.generator.constants.TemplateEnum;
import com.gss.module.generator.entity.BaseEntity;
import com.gss.module.generator.entity.FieldEntity;

import java.util.List;

/**
 * @author: DYang
 * @since: 2023/5/26
 * @description: 实体类转sql
 */
public class EntityToPgSqlGenerator {


    /**
     * 实体类转sql
     * @param baseEntity
     */
    public static void builder(String fileDir,BaseEntity baseEntity){
        String tableName = baseEntity.getTableName();
        String entityDesc = baseEntity.getEntityDesc();

        List<FieldEntity> fieldList = baseEntity.getFieldList();
        String contentSql = buildSql(tableName,entityDesc,fieldList);

        //保存到指定文件
        saveEntityFile(tableName,contentSql,fileDir);
    }

    /**
     * 将数据写道指定文件
     * @param tableName
     * @param contentSql
     * @param fileDir
     */
    private static void saveEntityFile(String tableName,String contentSql,String fileDir) {
        fileDir = fileDir + "/" + tableName + CommonConstants.SQL_FILE;
        FileUtil.writeString(contentSql, fileDir, "UTF-8");
    }

    /**
     * 构建sql语句
     * @param tableName  表名
     * @param entityDesc 表描述
     * @param fieldList  字段
     * @return
     */
    private static String buildSql(String tableName,String entityDesc, List<FieldEntity> fieldList) {
        StringBuilder tableBuilder = new StringBuilder();
        StringBuilder commentBuilder = new StringBuilder();

        String tableDesc = "-- " + tableName + " " + entityDesc;
        tableBuilder.append(tableDesc + "\n");
        //主键序列
        tableBuilder.append("DROP SEQUENCE IF EXISTS \"public\".\""+ tableName +"_Id_seq\";\n");
        tableBuilder.append("CREATE SEQUENCE \"public\".\""+ tableName +"_Id_seq\"\n");
        tableBuilder.append("INCREMENT 1\n");
        tableBuilder.append("MINVALUE  1\n");
        tableBuilder.append("MAXVALUE 9223372036854775807\n");
        tableBuilder.append("MAXVALUE 9223372036854775807\n");
        tableBuilder.append("START 1\n");
        tableBuilder.append("CACHE 1;\n\n");

        tableBuilder.append("DROP TABLE IF EXISTS \"public\".\""+ tableName +"\";\n");
        tableBuilder.append("CREATE TABLE \"public\".\""+ tableName +"\" (\n");
        //字段
        for (int i = 0; i < fieldList.size(); i++) {
            FieldEntity entity = fieldList.get(i);
            String fieldSql = buildFieldSql(tableName,entity);
            if (fieldSql == null) {
                continue;
            }
            if (i != fieldList.size() - 1) {
                tableBuilder.append(fieldSql).append(",\n");
            }else {
                tableBuilder.append(fieldSql).append("\n");
            }
        }
        tableBuilder.append(");\n\n");

        //注释
        for (FieldEntity entity : fieldList) {
            String fieldDesc = entity.getFieldDesc();
            String fieldName = entity.getFieldName();
            fieldName = transformSqlCode(fieldName);
            commentBuilder.append("COMMENT ON COLUMN \"public\".\""+ tableName +"\".\""+ fieldName +"\" IS '"+ fieldDesc +"';\n");
        }
        tableBuilder.append(commentBuilder);

        return tableBuilder.toString();
    }

    /**
     * 构建字段信息
     * @param tableName
     * @param entity
     * @return
     */
    private static String buildFieldSql(String tableName,FieldEntity entity) {
        String fieldSql = "";
        String fieldType = entity.getFieldType();
        String fieldName = entity.getFieldName();
        fieldName = transformSqlCode(fieldName);

        TemplateEnum templateEnum = TemplateEnum.getTemplateEnum(fieldType);
        switch (templateEnum) {
            case BOOLEAN:
                fieldType = "bool";
                break;
            case CHAR:
                fieldType = "CHAR(1)";
                break;
            case SHORT:
                fieldType = "int2";
                break;
            case INTEGER:
                fieldType = "int4";
                break;
            case LONG:
                fieldType = "int8";
                break;
            case FLOAT:
                fieldType = "float4";
                break;
            case DOUBLE:
                fieldType = "float8";
                break;
            case STRING:
                fieldType = "varchar(64)";
                break;
            case DATE:
                fieldType = "timestamp(0)";
                break;
            default:
                fieldType = "";
                break;
        }
        if (fieldType == "") {
            return null;
        }
        fieldSql = "  " + fieldName + " " + fieldType;
        if (entity.isPk()) {
            fieldSql += " NOT NULL DEFAULT nextval('"+ tableName +"_Id_seq'::regclass)";
        }
        return fieldSql;
    }

    /**
     * 把驼峰字段转换为下划线
     * @param fieldName
     * @return
     */
    private static String transformSqlCode(String fieldName) {
        int length = fieldName.length();
        StringBuilder newVal = new StringBuilder();
        for (int i = 0; i < length; i++) {
            char ch = fieldName.charAt(i);
            if (ch > 'A' && ch <= 'Z') {
                if (i == 0) {
                    newVal.append((String.valueOf(ch)).toLowerCase());
                }else {
                    newVal.append(("_" + ch).toLowerCase());
                }
            }else {
                newVal.append(ch);
            }
        }
        return newVal.toString();
    }

}
